<template>
  <div :style="style">
    <div ref="editor" style="height: 100%; width: 100%"></div>
    <div class="terminal" v-if="showTerminal">
      <ul class="menu">
        <li class="select" :count="errList.length">问题</li>
      </ul>
      <i class="el-icon-close close" @click="showTerminal = false"></i>
      <div class="err-msg">
        <div
          class="err-item"
          v-for="item of errList"
          :key="item.key"
          @click="setCursorPosition(item.startLineNumber, item.startColumn)"
        >
          <i class="el-icon-circle-close err-icon"></i>
          <span>{{ item.message }}</span>
          <span class="cursor-position"
            >[{{ item.startLineNumber }}, {{ item.startColumn }}]</span
          >
        </div>
      </div>
    </div>
  </div>
</template>

<script>
module.exports = {
  props: {
    width: { type: [String, Number], default: '100%' },
    height: { type: [String, Number], default: '100%' },
    code: { type: String, default: '' },
    language: { type: String, default: 'json' },
    theme: { type: String, default: 'vs-dark' },
    fontsize: { type: [String, Number], default: '16px' },
    fontfamily: { type: String, default: 'DejaVuSansMono' },
    disabl_short_cut_save: { type: Boolean, default: false },
    disable_warn: { type: Boolean, default: false },
  },
  data: function () {
    return {
      baseCode: this.code,
      editor: null,
      errList: [],
      showTerminal: false,
      style: {
        height: this.height,
        width: this.width,
      },
    };
  },
  methods: {
    setCursorPosition(lineNumber, column) {
      this.editor.focus();
      this.editor.setPosition({ lineNumber, column });
    },
  },
  watch: {
    code() {
      this.baseCode = this.code;
      this.editor.setValue(this.code);
    },
    language(newLanguage) {
      const value = this.editor.getValue();
      const model = monaco.editor.createModel(value, newLanguage);
      this.editor.setModel(model);
    },
  },
  mounted() {
    this.editor = monaco.editor.create(this.$refs.editor, {
      value: this.code,
      language: this.language,
      theme: this.theme,
      fontSize: this.fontsize,
      automaticLayout: true,
    });

    setTimeout(() => {
      this.errList = monaco.editor.getModelMarkers({ resource: this.editor.getModel().uri }).map((item) => {
        item.key = Math.random();
        return item;
      });

      if (this.errList.length > 0) {
        this.showTerminal = true;
      }
    }, 1000);

    // 但光标位置发生变化
    this.editor.onDidChangeCursorPosition((event) => {
      this.$emit('cursor-position', event.position);
    });

    this.editor.onDidChangeModelContent(() => {
      this.$emit('change', this.editor.getValue() !== this.code);
      setTimeout(() => {
        this.errList = monaco.editor.getModelMarkers({ resource: this.editor.getModel().uri }).map((item) => {
          item.key = Math.random();
          return item;
        });
      }, 1000);
    });

    this.editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.US_BACKTICK, () => {
      this.showTerminal = !this.showTerminal;
    });

    this.editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, () => {
      if (this.disabl_short_cut_save) {
        return;
      }
      const markers = monaco.editor.getModelMarkers({
        resource: this.editor.getModel().uri,
      });
      if (markers.length > 0) {
        this.errList = markers;
        this.showTerminal = true;
        return;
      }
      if (this.disable_warn) {
        this.$emit('save', this.editor.getValue());
        return;
      }
      this.$confirm('确定修改吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.$emit('save', this.editor.getValue());
        })
        .catch(() => {});
    });

    this.$emit('get-value', () => {
      return this.editor.getValue();
    });
  },
};
</script>

<style scoped>
.terminal {
  background: #1e1e1e;
  height: var(--terminal-height);
  border-top: 1px solid #80808059;
  width: 100%;
  position: relative;
  top: calc(0px - var(--terminal-height));
}

.menu {
  font-size: 11px;
  margin: 0 auto;
  padding: 0;
}

.menu li {
  color: #e7e7e7;
  list-style: none;
  margin: 4px 10px 3px 12px;
  line-height: 24px;
  display: inline-block;
  cursor: pointer;
  transition: transform 50ms ease;
  border-bottom: 1px solid #ccc;
}
.menu li:after {
  content: attr(count);
  color: #ffffff;
  background-color: #4d4d4d;
  padding: 3px 5px;
  border-radius: 11px;
  font-size: 11px;
  min-width: 18px;
  height: 18px;
  line-height: 11px;
  font-weight: 400;
  text-align: center;
  box-sizing: border-box;
  position: absolute;
  top: 8px;
  left: 45px;
}

.err-msg {
  color: #fff;
  font-weight: 100;
  font-size: 13px;
  cursor: pointer;
}

.err-item:hover {
  background: #2a2d2e;
}

.err-icon {
  margin: 6px 0px 6px 12px;
  color: rgb(244, 135, 113);
  font-size: 16px;
}

.cursor-position {
  color: #acacac;
}

.close {
  color: #ccc;
  cursor: pointer;
  display: inline-block;
  position: absolute;
  top: 8px;
  right: 15px;
}

* {
  --terminal-height: 180px;
}
</style>